<template>
  <div class="WebglPointsDiv"></div>
</template>

<script>
import * as THREE from 'three';
import * as BufferGeometryUtils from 'three/examples/jsm/utils/BufferGeometryUtils.js';
export default {
  name: "WebglPoints",
  mounted() {
    this.initWebgl();
  },
  methods: {
    initWebgl() {
      // 顶点着色器
      let pointShader = `
      attribute float size;
      attribute vec3 customColor;
      varying vec3 vColor;
      void main() {
          vColor = customColor;
          vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
          gl_PointSize = size * ( 300.0 / -mvPosition.z );
          gl_Position = projectionMatrix * mvPosition;
      }
      `;
      // 片元着色器
      let frameShader = `
        uniform vec3 color;
        uniform sampler2D pointTexture;
        uniform float alphaTest;
        varying vec3 vColor;
        void main() {
            gl_FragColor = vec4( color * vColor, 1.0 );
            gl_FragColor = gl_FragColor * texture2D( pointTexture, gl_PointCoord );
            if ( gl_FragColor.a < alphaTest ) discard;
        }
      `;
      const container = document.getElementsByClassName( 'WebglPointsDiv' )[0];
      let targetBox = new THREE.BoxGeometry(100, 100, 100, 16, 16, 16);
      targetBox.deleteAttribute( 'normal' );
      targetBox.deleteAttribute( 'uv' );
      targetBox = BufferGeometryUtils.mergeVertices( targetBox );

      const positionAttribute = targetBox.getAttribute( 'position' );

      const colors = [];
      const sizes = [];

      const color = new THREE.Color();

      for ( let i = 0, l = positionAttribute.count; i < l; i ++ ) {

        color.setHSL( 0.01 + 0.1 * ( i / l ), 1.0, 0.5 );
        // 把颜色存储在指定的位置
        color.toArray( colors, i * 3 );

        sizes[ i ] = 10;

      }

      const geometry = new THREE.BufferGeometry();
      geometry.setAttribute( 'position', positionAttribute );
      geometry.setAttribute( 'customColor', new THREE.Float32BufferAttribute( colors, 3 ) );
      geometry.setAttribute( 'size', new THREE.Float32BufferAttribute( sizes, 1 ) );

      //

      const material = new THREE.ShaderMaterial( {

        uniforms: {
          color: { value: new THREE.Color( 0xffffff ) },
          pointTexture: { value: new THREE.TextureLoader().load( 'disc.png' ) },
          alphaTest: { value: 0.9 }
        },
        vertexShader: pointShader,
        fragmentShader: frameShader

      } );

      const particles = new THREE.Points( geometry, material );
      let scene = new THREE.Scene();
      scene.add( particles );

      let camera = new THREE.PerspectiveCamera(45, container.clientWidth/container.clientHeight, 1, 2000);
      camera.position.z = 250;

      let renderer = new THREE.WebGLRenderer();
      renderer.setPixelRatio( window.devicePixelRatio );


      renderer.setSize( container.clientWidth, container.clientHeight);
      container.appendChild(renderer.domElement);

      let animate = function () {
        requestAnimationFrame( animate );
        particles.rotation.x += 0.01;
        particles.rotation.y += 0.01;
        renderer.render(scene, camera);
      }
      animate();
    }
  }
}
</script>

<style scoped lang="less">
   .WebglPointsDiv {
     height: 100%;
   }
</style>